package com.netrust.cmsx.admin.modules.sys.service;

import java.util.Arrays;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.netrust.cmsx.admin.modules.sys.common.AStatic;
import com.netrust.cmsx.core.exception.ProvideException;
import com.netrust.cmsx.core.jpa.Criteria;
import com.netrust.cmsx.core.jpa.Restrictions;
import com.netrust.cmsx.core.page.PageKey;
import com.netrust.cmsx.core.persist.TreeUtil;
import com.netrust.cmsx.core.service.TreeService;
import com.netrust.cmsx.entity.module.sys.Dict;
import com.netrust.cmsx.entity.module.sys.Menu;
import com.netrust.cmsx.persist.module.sys.DictDao;
import com.netrust.cmsx.utils.collections.CollectionUtils;
import com.netrust.cmsx.utils.excute.ExcuteTime;
import com.netrust.cmsx.utils.relfect.Reflections;
import com.netrust.cmsx.utils.string.StringUtils;


@Service("dictService")
@Transactional(readOnly = true)
public class DictService extends TreeService<Dict,String,DictDao>{
	
	public List<Dict> findByDelFlagOrderByTypeDesc(){
		return dao.findByDelFlagOrderByTypeDesc(false);
	}
	
	public List<Dict> findAllList(){
		Criteria<Dict> criteria=new Criteria<Dict>();

		criteria.add(Restrictions.eq("delFlag",false));
		//criteria.orderByASC("sort");
		
		return dao.findAll(criteria);
	}
	
	public Page<Dict> findAllList(PageKey pk){
		final String key=pk.getKey();
		Page<Dict> sas= dao.findAll(new Specification<Dict>() {
					public Predicate toPredicate(Root<Dict> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
							Predicate p = cb.equal(root.get("delFlag").as(boolean.class), false);
							
							Predicate p1 = cb.like(root.get("code").as(String.class),"%"+key+"%");
							Predicate p2 = cb.like(root.get("lable").as(String.class),"%"+key+"%");
							Predicate p3 = cb.like(root.get("type").as(String.class),"%"+key+"%");
							Predicate p4 = cb.like(root.get("description").as(String.class),"%"+key+"%");
							
							p=cb.and(p,cb.or(p1,p2,p3,p4));
							
							cq.where(p);
							return cq.getRestriction();
						}
				},new PageRequest(pk.getPageNum(), pk.getPageSize(), Direction.DESC, "sort","type"));
		return sas;
	}
	
	@Transactional(readOnly = false)
	public void saveDict(Dict dict) throws ProvideException{
		if(StringUtils.isNotBlank(dict.getId())){
			Dict old=dao.findOne(dict.getId());
			try {
				
				if(AStatic.zero.equals(dict.getPid())){
					old.setPids(dict.getPid()+",");					
				}else{
					//判断父节点是否循环调用
					List<Dict> children=dao.findAllChilds(old, "getTableChilds");
					@SuppressWarnings("unchecked")
					List<String> cids=CollectionUtils.extractToList(children,"id");
					if(cids.contains(dict.getPid())){
						throw ProvideException.unchecked(new Exception("父节点  = "+dict.getPid()+" 设置不正确，循环调用造成数据混乱"));
					}
					
					BeanUtils.copyProperties(dict, old,"children","delFlag");
					Dict parent=dao.findOne(dict.getPid());
					old.setPids(parent.getPids()+dict.getPid()+",");					
				}
				
				this.save(old);
			} catch (Exception e) {
				throw ProvideException.unchecked(e);
			}
			
		}else{
			dict.setDelFlag(false);
			dict.setWhetherNew(true);
			if(!AStatic.zero.equals(dict.getPid())){
				Dict parent=dao.findOne(dict.getPid());
				dict.setPids(parent.getPids()+dict.getPid()+",");
			}else{				
				dict.setPids(dict.getPid()+",");
			}
			
			this.save(dict);
		}
	}
	
	
	@Transactional(readOnly = false)
	public void delete(Dict dict) {
		if(dict!=null&&dict.getId()!=null){
			this.delete(dict.getId());		
		}
	}
	
	@Transactional(readOnly = false)
	public void deleteInFlag(Dict dict) {
		if(dict!=null&&dict.getId()!=null){
			dict=dao.findOne(dict.getId());
			dict.setDelFlag(true);
			dict.setWhetherNew(false);
			this.save(dict);	
		}
	}

	@Override
	public List<Dict> findTree() {
		List<Dict> dicts=dao.findByDelFlagOrderBySortAsc(false);
		return new TreeUtil<Dict>().getChildTree(dicts);
	}

	@Override
	public List<Dict> findTree(Dict entity) {
		List<Dict> dicts=dao.findByDelFlagOrderBySortAsc(false);
		return new TreeUtil<Dict>().getChildTree(dicts,entity.getId());
	}
	

	/**
	 * 获取直属子节点
	 * @param entity
	 * @return
	 */
	@Transactional(propagation=Propagation.SUPPORTS)
	public List<Dict> findChild(Dict entity) {
		List<Dict> dicts=dao.findByDelFlagOrderBySortAsc(false);
		return new TreeUtil<Dict>().getChildList(dicts,entity);
	}
	
	@Override
	public List<Dict> findChilds(Dict entity, String func) {
		List<Dict> list=dao.findAllChilds(entity, func);
		
		CollectionUtils.select(list, new org.apache.commons.collections.Predicate() {//去掉自己
			@Override
			public boolean evaluate(Object object) {
				if(((Dict) object).getId().equals(entity.getId())){
					return false;
				}
				return false;
			}
		});
		
		return list;
	}

	@Override
	public List<Dict> findParents(Dict entity, String func) {
		List<Dict> list=dao.findAllParents(entity, func);
		
		CollectionUtils.select(list, new org.apache.commons.collections.Predicate() {//去掉自己
			@Override
			public boolean evaluate(Object object) {
				if(((Dict) object).getId().equals(entity.getId())){
					return false;
				}
				return false;
			}
		});
		
		return list;
	}
	
	
	@Transactional(propagation=Propagation.SUPPORTS)
	public Dict findById(String id){
		return dao.findById(id);
	}


}
